﻿using Furion;
using Furion.DataEncryption;
using Furion.DataEncryption.Extensions;
using Furion.DynamicApiController;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using Mrhd.Core;
using Mrhd.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Mrhd.Application
{
    /// <summary>
    /// 账户服务
    /// </summary>
    [AllowAnonymous]
    public class AccountAppService : IDynamicApiController
    {
        private readonly IAccountService _service;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IDistributedCache _distributedCache;
        public AccountAppService(IAccountService userService,
            IHttpContextAccessor httpContextAccessor,
            IDistributedCache distributedCache)
        {
            _service = userService;
            _httpContextAccessor = httpContextAccessor;
            _distributedCache = distributedCache;
        }

        /// <summary>
        /// 用户获取token
        /// </summary>
        /// <param name="info">登录信息</param>
        /// <returns></returns>
        public async Task<LoginResultDto> PostToken(LoginInfoDTO info)
        {
            LoginResultDto result;

            if (!string.IsNullOrEmpty(info.UserName))        // 当用户名不为空时，则规定为是网站用户登录
            {
                // 网站端用户
                result = await WebLoginAsync(info);
            }
            else
            {
                // 移动端用户
                result = await MobileLoginAsync(info);
            }

            return result;
        }

        /// <summary>
        /// 网站用户
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        private async Task<LoginResultDto> WebLoginAsync(LoginInfoDTO info)
        {
            var result = new LoginResultDto();
            // 网站用户
            var user = await _service.GetUserByUserNameAsync(info.UserName);
            if (user == null)
            {
                result.Data = "用户不存在";
                return result;
            }
            if (info.Password.ToMD5Compare(info.Password))
            {
                result.Data = "密码错误";
                return result;
            }

            // 创建token
            var token = GenenateToken(new Dictionary<string, object>()
                {
                    { "id", user.Id },                      // 存储Id
                    { "userName", user.UserName },          // 存储用户名
                    { "name", user.FullName },              // 存储姓名
                    { "isAdmin", user.IsAdmin ? 1 : 0 }     // 是否是管理员
                }, 10080);

            result.Success = true;
            result.Data = token;
            return result;
        }

        /// <summary>
        /// 移动端用户
        /// </summary>
        /// <param name="info"></param>
        /// <returns></returns>
        private async Task<LoginResultDto> MobileLoginAsync(LoginInfoDTO info)
        {
            var openId = info.OpenId;
            var sessionKey = string.Empty;
            if (string.IsNullOrEmpty(openId))
            {
                (openId, sessionKey) = await WeixinHelper.Weixin.GetOpenIdAsync(info.Code); // 通过加密字符串获取openid
            }
            var user = await _service.GetUserByOpenIdAsync(openId);
            // 如果用户不存在，则创建
            if (user == null)
            {
                user = await _service.CreateUserAsync(openId);
            }
            // 创建token
            GenenateToken(new Dictionary<string, object>()
                {
                    { "mobileid", user.Id },                        // 存储Id
                }, 10080);
            // 保存会话密钥到分布式缓存
            if (!string.IsNullOrEmpty(sessionKey))
            {
                await _distributedCache.SetStringAsync($"SessionKey:{user.Id}", sessionKey);
            }
            return new LoginResultDto { Success = true, Data = user.Adapt<UserMobileDto>() };
        }

        /// <summary>
        /// 根据指定的参数生成token
        ///     token过期时间配置中确定
        /// </summary>
        /// <param name="dic">token声明参数</param>
        /// <param name="expire">刷新token过期时间</param>
        /// <returns></returns>
        private string GenenateToken(Dictionary<string, object> dic, int expire)
        {
            // 创建token
            var token = JWTEncryption.Encrypt(dic);
            // 获取刷新token
            var refreshToken = JWTEncryption.GenerateRefreshToken(token, expire);
            // 设置响应报文头
            _httpContextAccessor.HttpContext.Response.Headers["access-token"] = token;
            _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;

            return token;
        }

    }

}
